package com.gp8.tier3;

import java.io.Serializable;
import java.rmi.RemoteException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Scanner;
import java.util.Map.Entry;

//Il faut faire des return pour renvoyer les objets au tier2, les syso ne servent qu'au log serveur (tier3)

public class ServiceGestionPiaffeurImpl implements ServiceGestionPiaffeur, Runnable, Serializable {
	
	private static final long serialVersionUID = 1L;
	private int idGeneralPiaffeur = 0;
	private int idGeneralPiafferie = 0;
	private ArrayList<Piaffeur> listPiaffeursA = new ArrayList<Piaffeur>(); //Piaffeur abonnés
	private ArrayList<Piaffeur> listPiaffeursC = new ArrayList<Piaffeur>(); //Piaffeur connectés
	private HashMap<Piaffeur, ArrayList<Piaffeur>> listPiaffeursAbonnement = new HashMap<Piaffeur, ArrayList<Piaffeur>>(); //Liste des abonnements par Piaffeur
	private HashMap<Piaffeur, ArrayList<Piafferie>> listPiaffeursMessage = new HashMap<Piaffeur, ArrayList<Piafferie>>(); //Liste des messages par Piaffeur
	
	@Override
	public Piaffeur getAbonne(int id) throws RemoteException {
		Piaffeur pPiaffeur = new Piaffeur(id, "", "", "");
		int index = listPiaffeursA.indexOf(pPiaffeur);
		
		return listPiaffeursA.get(index);
	}
	
	@Override
	public Piaffeur CreationCompte(String pMail, String pPseudo, String pPassword) throws RemoteException {
		idGeneralPiaffeur++;
		Piaffeur piaffeur = new Piaffeur(idGeneralPiaffeur, pMail, pPseudo, pPassword);
		if (!listPiaffeursA.contains(piaffeur)) {
			listPiaffeursA.add(piaffeur);
			System.out.println("Compte créé avec mail = '" + pMail + "', pseudo = '" + pPseudo + "' et mdp = '" + pPassword + "'");
			return piaffeur;
		} else {
			System.out.println("Compte existant avec mail = '" + pMail + "', pseudo = '" + pPseudo + "' et mdp = '" + pPassword + "'");
			return null;
		}
	}

	@Override
	public Piaffeur ConnexionCompte(String pMail, String pPassword) throws RemoteException {
		int i = 0;
		while (i < listPiaffeursA.size()) {
			if (listPiaffeursA.get(i).getMail().equals(pMail) && listPiaffeursA.get(i).getPassword().equals(pPassword)) {
				break;
			}
			i++;
		}
		if (i < listPiaffeursA.size()) {
			Piaffeur piaffeur = listPiaffeursA.get(i);
			if (!listPiaffeursC.contains(piaffeur)) {
				listPiaffeursC.add(piaffeur);
			}
			System.out.println("Connexion de " + piaffeur.getPseudo());
			return piaffeur;
		} else {
			System.out.println("Tentative de connexion avec mail = '" + pMail + "' et mdp = '" + pPassword + "'");
			return null;
		}		
	}

	@Override
	public Boolean DeconnexionCompte(int pID) throws RemoteException {

		Boolean reponse = false;
		Piaffeur pPiaffeur = getAbonne(pID);
		if (listPiaffeursC.contains(pPiaffeur)) {
			reponse = true;
			listPiaffeursC.remove(pPiaffeur);
			System.out.println("Deconnexion de " + pPiaffeur.getPseudo());
		}

		return reponse;
	}
	
	@Override
	public Boolean SuppressionCompte(int pID) throws RemoteException {

		Boolean reponse = false;
		//On vérifie que la personne est connecté avant de supprimer son compte
		Piaffeur pPiaffeur = getAbonne(pID);
		if (listPiaffeursC.contains(pPiaffeur)) {
			if (listPiaffeursA.contains(pPiaffeur)) {
				reponse = true;
				listPiaffeursA.remove(pPiaffeur);
				if (listPiaffeursAbonnement.containsKey(pPiaffeur)) {
					listPiaffeursAbonnement.remove(pPiaffeur);
				}
				if (listPiaffeursMessage.containsKey(pPiaffeur)) {
					listPiaffeursMessage.remove(pPiaffeur);
				}				
				System.out.println("Suppression de " + pPiaffeur.getPseudo());
			}
			listPiaffeursC.remove(pPiaffeur);
			System.out.println("Deconnexion de " + pPiaffeur.getPseudo());
		}
		
		return reponse;
	}
	
	@Override
	public Boolean AjouterAbonnement(int pIDSuiveur, int pIDSuivi) throws RemoteException {

		Boolean reponse = false;
		//On vérifie que la personne est connecté avant d'ajouter un abonnement
		Piaffeur pPiaffeurSuiveur = getAbonne(pIDSuiveur);
		Piaffeur pPiaffeurSuivi = getAbonne(pIDSuivi);
		if (listPiaffeursC.contains(pPiaffeurSuiveur)) {
			//On verifie l'existance de la personne à suivre
			if (listPiaffeursA.contains(pPiaffeurSuivi)) {
				reponse = true;
				ArrayList<Piaffeur> liste = listPiaffeursAbonnement.get(pPiaffeurSuiveur);
				if(liste == null) {
					reponse = true;
					liste = new ArrayList<Piaffeur>();
					liste.add(pPiaffeurSuivi);
					listPiaffeursAbonnement.put(pPiaffeurSuiveur, liste);
					System.out.println(pPiaffeurSuiveur.getPseudo() + " suit " + pPiaffeurSuivi.getPseudo());
			    } else if (!liste.contains(pPiaffeurSuivi)) {
			    	reponse = true;
			    	listPiaffeursAbonnement.get(pPiaffeurSuiveur).add(pPiaffeurSuivi);
			    	System.out.println(pPiaffeurSuiveur.getPseudo() + " suit " + pPiaffeurSuivi.getPseudo());
			    }
			}
		}
		
		return reponse;
	}
	
	@Override
	public Boolean SupprimerAbonnement(int pIDSuiveur, int pIDSuivi) throws RemoteException {

		Boolean reponse = false;
		//On vérifie que la personne est connecté avant de supprimer un abonnement
		Piaffeur pPiaffeurSuiveur = getAbonne(pIDSuiveur);
		Piaffeur pPiaffeurSuivi = getAbonne(pIDSuivi);
		if (listPiaffeursC.contains(pPiaffeurSuiveur)) {
			ArrayList<Piaffeur> liste = listPiaffeursAbonnement.get(pPiaffeurSuiveur);
			if(liste != null && listPiaffeursAbonnement.containsKey(pPiaffeurSuivi)) {
				reponse = true;
				listPiaffeursAbonnement.get(pPiaffeurSuiveur).remove(pPiaffeurSuivi);
				System.out.println(pPiaffeurSuiveur.getPseudo() + " a supprimé un abonnement.");
			}
		}
		
		return reponse;
	}
	
	@Override
	public ArrayList<Piaffeur> MesAbonnements(int pID) throws RemoteException {

		//On vérifie que la personne est connecté avant de chercher les abonnement
		Piaffeur pPiaffeur = getAbonne(pID);
		if (listPiaffeursC.contains(pPiaffeur)) {
			System.out.println("Résultat abonnement " + listPiaffeursAbonnement.get(pPiaffeur));
			return listPiaffeursAbonnement.get(pPiaffeur);
		} else {
			System.out.println("Aucun abonnement : " + pPiaffeur.getPseudo());
			return null;
		}
	}
	
	@Override
	public ArrayList<Piaffeur> MesAbonnes(int pID) throws RemoteException {
		ArrayList<Piaffeur> listPiaffeursAbonnes = new ArrayList<Piaffeur>(); //Liste de mes abonnes
		
		//On vérifie que la personne est connecté avant de chercher les abonnes
		Piaffeur pPiaffeur = getAbonne(pID);
		if (listPiaffeursC.contains(pPiaffeur)) {

			for (Entry<Piaffeur, ArrayList<Piaffeur>> piaffeurAbonnement : listPiaffeursAbonnement.entrySet()) {
				Piaffeur piaffeur = piaffeurAbonnement.getKey();
				ArrayList<Piaffeur> listeAbonnement = piaffeurAbonnement.getValue();
				
				if (listeAbonnement.contains(pPiaffeur)) {
					listPiaffeursAbonnes.add(piaffeur);
				}
			}
			if (!listPiaffeursAbonnes.isEmpty()) {
				System.out.println("Résultat abonnes " + listPiaffeursAbonnes);
				return listPiaffeursAbonnes;
			} else {
				System.out.println("Aucun abonne : " + pPiaffeur.getPseudo());
				return null;
			}
		}
		return null;
	}
	
	@Override
	public Boolean AjouterMessage(int pID, String message) throws RemoteException {
		
		Boolean reponse = false;
		//On vérifie que la personne est connecté avant d'ajouter un message
		Piaffeur pPiaffeur = getAbonne(pID);
		if (listPiaffeursC.contains(pPiaffeur)) {
			reponse = true;
			ArrayList<Piafferie> liste = listPiaffeursMessage.get(pPiaffeur);
			idGeneralPiafferie++;
			Piafferie piafferie = new Piafferie(idGeneralPiafferie, pPiaffeur, message);
			if(liste == null) {
				liste = new ArrayList<Piafferie>();
				liste.add(piafferie);
				listPiaffeursMessage.put(pPiaffeur, liste);
		    } else if (!liste.contains(piafferie)) {
		    	listPiaffeursMessage.get(pPiaffeur).add(piafferie);
		    }
			System.out.println("Message de " + pPiaffeur.getPseudo() + " ajouté");
		}
		return reponse;
	}
	
	@Override
	public Boolean SupprimerMessage(int pID, int pIDMessage) throws RemoteException {
		
		Boolean reponse = false;
		//On vérifie que la personne est connecté avant de supprimer un message
		Piaffeur pPiaffeur = getAbonne(pID);
		if (listPiaffeursC.contains(pPiaffeur)) {
			ArrayList<Piafferie> liste = listPiaffeursMessage.get(pPiaffeur);
			Piafferie pPiafferie = new Piafferie(pIDMessage, null, "");
			int index = liste.indexOf(pPiafferie);
			pPiafferie = liste.get(index);
			if(liste != null && liste.contains(pPiafferie)) {
				reponse = true;
				listPiaffeursMessage.get(pPiaffeur).remove(pPiafferie);
				System.out.println("Message de " + pPiaffeur.getPseudo() + " supprimé");
			}
		}
		return reponse;
	}
	
	@Override
	public ArrayList<Piafferie> MesMessages(int pID) throws RemoteException {
		//On vérifie que la personne est connecté avant de chercher les abonnement
		Piaffeur pPiaffeur = getAbonne(pID);
		if (listPiaffeursC.contains(pPiaffeur)) {
			System.out.println("Résultat messages " + listPiaffeursMessage.get(pPiaffeur));
			return listPiaffeursMessage.get(pPiaffeur);
		} else {
			System.out.println("Aucun message : " + pPiaffeur.getPseudo());
			return null;
		}
	}
	
	@Override
	public ArrayList<Piaffeur> RecherchePiaffeur(String pseudo) throws RemoteException {
		ArrayList<Piaffeur> listPiaffeursR = new ArrayList<Piaffeur>(); //Résultat de la recherche

		for (Piaffeur piaffeur : listPiaffeursA) {
			if (piaffeur.getPseudo().matches(".*"+pseudo+".*")) {
				listPiaffeursR.add(piaffeur);
			}
		}
		if (!listPiaffeursR.isEmpty()) {
			System.out.println("Résultat " + listPiaffeursR);
			return listPiaffeursR;
		} else {
			System.out.println("Aucun résultat pour : " + pseudo);
			return null;
		}
	}
	
	@Override
	public ArrayList<Piafferie> RecherchePiafferie(String message) throws RemoteException {
		ArrayList<Piafferie> listPiafferie = new ArrayList<Piafferie>(); //Résultat de la recherche

		for (Entry<Piaffeur, ArrayList<Piafferie>> listeMessage : listPiaffeursMessage.entrySet()) {
			//Piaffeur piaffeur = listeMessage.getKey();
			ArrayList<Piafferie> listePiafferie = listeMessage.getValue();
			
			for (Piafferie piafferie : listePiafferie) {
				if (piafferie.getMessage().matches(".*"+message+".*")) {
					listPiafferie.add(piafferie);
				}
			}
		}
		if (!listPiafferie.isEmpty()) {
			System.out.println("Résultat " + listPiafferie);
			return listPiafferie;
		} else {
			System.out.println("Aucun résultat pour : " + message);
			return null;
		}
	}
	
	@Override
	public ArrayList<Piafferie> MaTimeline(int pID) throws RemoteException {
		ArrayList<Piafferie> listPiafferie = new ArrayList<Piafferie>(); //Résultat de la timeline
		ArrayList<Piaffeur> listPiaffeur = new ArrayList<Piaffeur>(); //Liste des abonnements

		Piaffeur pPiaffeur = getAbonne(pID);
		if (listPiaffeursC.contains(pPiaffeur)) {
			listPiaffeur = listPiaffeursAbonnement.get(pPiaffeur);
		}
		
		for (Piaffeur piaffeur : listPiaffeur) {
			ArrayList<Piafferie> listeMessage = listPiaffeursMessage.get(piaffeur);
			for (Piafferie piafferie : listeMessage) {
				listPiafferie.add(piafferie);
			}
		}
		
		Collections.sort(listPiafferie);
		
		if (!listPiafferie.isEmpty()) {
			System.out.println("Résultat " + listPiafferie);
			return listPiafferie;
		} else {
			System.out.println("Aucun résultat dans la timeline.");
			return null;
		}
	}
	
	@Override
	public synchronized void run() {
		boolean live = true;
		while(live) {		
			Scanner scanInput;
			String choix = "N";
			System.out.println("Voulez-vous quitter ?");
			scanInput = new Scanner(System.in);
			choix = scanInput.nextLine();
			
			if (choix.equals("O")) {
				ServiceTroisiemeTier.Save();
				live = false;
			}
		}
	}
}
